/**
 *  @fileOverview 模版设计器DEMO JS
 *  @requires jquery.js(1.6),jquery.cookie.js,board-designer.css,
 *            jquery-ui.js(sortable,button,sizeable,droggable,dropable),
 *            jquery-ui.css,json2.js(to support ie6/7)
 *  @author yuwei.zheng
 *  @version 1.0
 */
 
/**
 *  @description 测试用，默认看板数据
 */
var jsonData = {
	"fatherWindows": [{
		"id" : "win-con-1",
		"title" : "win-con-1",
		"hasborder" : true,
		"pos" : 1,
		"seq" : 1
	},{
		"id" : "win-con-2",
		"title" : "win-con-2",
		"hasborder" : false,
		"pos" : 1,
		"seq" : 1
	}],
	"subWindows" : [{
		"id" : "win-con-1-1",
		"fatherId" : "win-con-1",
		"title" : "win-con-1-1",
		"pos" : 1,
		"width" : 290,
		"height" : 280
	},{
		"id" : "win-con-2-1",
		"fatherId" : "win-con-2",
		"title" : "win-con-2-1",
		"pos" : 1,
		"width" : 290,
		"height" : 280		
	}],
	"customWindows" : [],
	"seq" : 2
};

var util = {
	/**
	 * @description 判断对象是否为空对象
	 */
	isEmptyObject : function(object){
		if (object === null || object === undefined) return true; else return false;
	},
	
	/**
	 * @description 判断字符串是否为空，如果引用对象为空也返回true
	 */
	isBlankString : function(object){
		if (this.isEmptyObject(object)) 
			return true; 
		else
			if (object == '') return true;
		else
			return false;
	}
};
/**
 *  @constructor BoardData
 *  @description 看板数据类
 *  @param {String || Object} jsonData json对象
 *  @author yuwei.zheng
 *  @version 2011年12月22日, PM 11:25:40
 */
function BoardData(jsonData){
	/* 父窗口数据 */
	this.fatherWindows = new Array();
	/* 子窗口数据 */
	this.subWindows = new Array();
	/* 自定义窗体 */
	this.customWindows = new Array();
	
	/* 父窗口序列值，只是为了防止生成重复ID */
	this.seq = 0;
	
	if (!(jsonData === null || jsonData === undefined)){
		if (typeof jsonData == "string"){
			jsonData = JSON.parse(jsonData);
		}
		this.fatherWindows = jsonData.fatherWindows;
		this.subWindows = jsonData.subWindows;
		this.customWindows = jsonData.customWindows;
		this.seq = jsonData.seq;
	}
	
}

BoardData.prototype = {
	/**
	 *  @description 添加一个父窗口
	 *  @param {Object} fatherWindow 父窗口的Json对象
	 */
	pushFatherWindow : function(fatherWindow){
		this.fatherWindows.push(fatherWindow);
	},

	/**
	 *  @description 添加一个子窗口
	 *  @param {Object} subWindow 子窗口的Json对象
	 */
	pushSubWindow : function(subWindow){
		this.subWindows.push(subWindow);
	},

	/**
	 *  @description 添加一个自定义窗体
	 *  @param {Object} customWindow 自定义窗体的Json对象
	 */
	pushCustomWindow : function(customWindow){
		this.customWindows.push(customWindow);
	},
	
	/**
	 *  @description 获取该父窗口下有多少个子窗口
	 *  @param {String} fatherWindowId 父窗口的id
	 *  @return {Num} 子窗口总数
	 */
	getSubWindowsLength : function(fatherWindowId){
		var count = 0;
		for (var i in this.subWindows){
			if (this.subWindows[i].fatherId == fatherWindowId){
				count++;
			}
		}
		return count;
	},

	/**
	 *  @description 获取有多少个父窗口
	 *  @return {Num} 父窗口数目
	 */
	getFatherWindowsLength : function(){
		return this.fatherWindows.length;
	},

	/**
	 *  @description 获取指定id的父窗口详细信息
	 *  @param {String} fatherWindowId 父窗口的id
	 *  @return {Object} 父窗口Json对象
	 */
	getFatherWindow : function(fatherWindowId){
		for (var i in this.fatherWindows){
			if (this.fatherWindows[i].id == fatherWindowId){
				return this.fatherWindows[i];
			}
		}
	},

	/**
	 *  @description 获取ID为subWindowId的子窗口信息
	 *  @param {String} subWindowId 子窗口的id
	 *  @return {Object} 子窗口Json对象
	 */
	getSubWindow : function(subWindowId){
		for (var i in this.subWindows){
			if (this.subWindows[i].id == subWindowId){
				return this.subWindows[i];
			}
		}
	},

	/**
	 *  @description 获取ID为subWindowId的子窗口信息
	 *  @param {String} customWindowId 子窗口的id
	 *  @return {Object} 子窗口Json对象
	 */
	getCustomWindow : function(customWindowId){
		for (var i in this.customWindows){
			if (this.customWindows[i].id == customWindowId){
				return this.customWindows[i];
			}
		}
	},
	
	/**
	 *  @description 删除指定ID的子板块
	 *  @param {String} subWindowId 子窗口的id
	 */
	deleteSubWindow : function(subWindowId){
		for (var i in this.subWindows){
			if (this.subWindows[i].id == subWindowId){
				this.subWindows.splice(i,1);
				break;
			}
		}
	}, 
	
	/**
	 *  @description 删除指定ID的子板块
	 *  @param {String} fatherWindowId 父窗口的id
	 */
	deleteFatherWindow : function(fatherWindowId){
		for (var i in this.fatherWindows){
			if (this.fatherWindows[i].id == fatherWindowId){
				this.fatherWindows.splice(i,1);
				break;
			}
		}
		var tmp = new Array();
		for (var i in this.subWindows){
			if (this.subWindows[i].father != fatherWindowId){
				tmp.push(this.subWindows[i]);
			}
		}
		this.subWindows = tmp;
	},
	
	/**
	 *  @description 删除指定ID的自定义板块
	 *  @param {String} customWindowId 子窗口的id
	 */
	deleteCustomWindow : function(customWindowId){
		for (var i in this.customWindows){
			if (this.customWindows[i].id == customWindowId){
				this.customWindows.splice(i,1);
				break;
			}
		}
	}
	
}

/**
 *  @constructor BoardDesigner
 *  @description 模块设计器类
 *  @author yuwei.zheng
 *  @version 2011年12月22日, PM 07:54:56
 */
function BoardDesigner(){
	/* 配置信息 */
	this.config = {
		mainContainer : '',												// 存放的DIV ID
		subDivStyle : "sub-win win-hasborder portlet",					// 子窗体的class
		subWinWidth : 290,												// 默认生成的子窗体宽度
		subWinHeight : 280,												// 默认生成的子窗体高度
		subWinGrid : 5,													// 默认窗体拖动位移偏量
		subWinMaxWidth : 920,											// 默认子窗体的最大宽度
		subWinMinWidth : 150,											// 默认子窗体的最小宽度
		subWinMinHeight : 40,											// 默认子窗体的最小高度
		cusWinWidth : 100,												// 默认自定义窗体的宽度		
		cusWinHeight : 30,												// 默认自定义窗体的高度
		adjustPiex : 2,													// 解决浏览器盒模型不同造成的偏量
		dragOpacity : 0.6,												// 各拖动组件拖动时的透明度值为0~1
		readOnly: false													// true表示只读，反之则可以编辑
	};
	
	/* 看板数据 */
	this.boardData = new BoardData(jsonData);	// 如果需要默认显示空白页面则把下面代码注释去掉并注释上条代码，this.boardData = new BoardData();
	
}

BoardDesigner.prototype = {
	/**
	 *  @description 初始化模块设计器。
	 *  @param {Object} config 配置信息
	 */
	init : function(config){
		// 未指定父窗体则直接返回
		if (config.mainContainer === null || config.mainContainer === undefined){
			return;
		}
		this.config.mainContainer = config.mainContainer;
		
		// 更新是否为只读模式
		if (!(config.readOnly === null || config.readOnly === undefined)){
			this.config.readOnly = config.readOnly;
		}
		
		// 获取cookie中的数据
		var tmp= $.cookie('boardData');
		if (tmp != null){
			this.boardData = new BoardData(tmp);
		}
		
		// 循环遍历父窗体数组，并生成对应窗体
		for (var fatherWindowTmp in this.boardData.fatherWindows){
			var fatherWindows = this.boardData.fatherWindows;
			if (fatherWindows[fatherWindowTmp] == null) continue;
			this.createFatherWindow(fatherWindows[fatherWindowTmp]);
		}

		// 循环遍历自定义窗体数组，并生成对应窗体
		for (var customWindowTmp in this.boardData.customWindows){
			var customWindows = this.boardData.customWindows;
			if (customWindows[customWindowTmp] == null) continue;
			this.createCustomWindow(customWindows[customWindowTmp]);
		}
		
		// 循环遍历子窗体数组，并生成对应窗体
		this.boardData.subWindows.sort(function(a, b){
			return a.pos - b.pos;
		});
		for (var subWindowTmp in this.boardData.subWindows){
			var subWindows = this.boardData.subWindows;
			if (subWindows[subWindowTmp] == null) continue;
			this.createSubWindow(subWindows[subWindowTmp]);
		}
		
		if (!this.config.readOnly){
			// 让最大的容器拥有排序属性
			$('#' + this.config.mainContainer).sortable({
				opacity: this.config.dragOpacity,
				revert: true,
				// 为了让占位的窗体和被拖动的一样大，父亲窗体因为可能比较大，所以让其高度固定为一个较小的值
				start: function(event, ui){
					$('.ui-sortable-placeholder').css({'height':70, 'width':$(ui.item).width()});
				}
			}).disableSelection();
			
			// 绑定父窗体变换位置的事件
			var boardDesigner = this;
			$('#' + this.config.mainContainer).bind('sortupdate', function(event, ui) {
				var newFatherWindows = new Array();
				$(this).children('.win-con').each(function(){
					newFatherWindows.push(boardDesigner.boardData.getFatherWindow($(this).attr('id')));
				});
				boardDesigner.boardData.fatherWindows = newFatherWindows;
			});
			
			// 让所有子窗口有排序属性
			$('.column').sortable({
				connectWith: ".column",
				opacity: this.config.dragOpacity,
				revert: true,
				// 为了让占位的窗体和被拖动的一样大
				start: function(event, ui){
					$('.ui-sortable-placeholder').css({'height':$(ui.item).height() - 6,'width':$(ui.item).width() - 6});
				}
			}).disableSelection();
			
			// 绑定子窗体变换位置的事件
			$('.column').bind('sortupdate', function(event, ui) {
				var fatherId = $(this).parent('.win-con').attr('id');
				$(this).children('.sub-win').each(function(index){
					var tmp = boardDesigner.boardData.getSubWindow($(this).attr('id'));
					tmp.pos = index + 1;
					tmp.fatherId = fatherId;
				});
				boardDesigner.boardData.subWindows.sort(function(a, b){
					return a.pos - b.pos;
				});
			});
			
		}

	},

	/**
	 *  @description 生成父窗口的代码。在初始化的时候调用。
	 *  @param {Object} fatherWindow 待生成自定义窗体对象
	 *  @param {String} id 待生成父窗口的id
	 *  @param {String} titleName 待生成父窗口的标题名
	 *  @param {Number} width 待生成父窗口的宽度
	 *  @param {Number} height 待生成父窗口的高度
	 */
	createFatherWindow : function(fatherWindow){
		// 生成HTML文本
		var htmlStr = '<div id="' + fatherWindow.id + '" class="win-con win-hasborder topics-unit">';
		
		// 判别不需要显示边框的情况
		if (!(this.config.readOnly && !fatherWindow.hasborder)){
			htmlStr += '<div class="unit-title">';
			htmlStr += '<div class="unit-title-left">';
			htmlStr += '<table border="0" cellspacing="0">';
			htmlStr += '<tr><td class="unit-title-text">' + fatherWindow.title + '</td>';
			htmlStr += '<td class="unit-title-end"></td>';
			htmlStr += '<td class="unit-title-con"></td></tr>';
			htmlStr += '</table></div>';
			if (!this.config.readOnly){
				htmlStr += '<div class="float-right" style="color: #0a6ffc;"><span class="unit-button"><input type="checkbox" class="hasBorderCheckbox" ';
				if (!util.isEmptyObject(fatherWindow) && fatherWindow.hasborder === true){
					htmlStr += 'checked="checked"';
				}
				htmlStr += '>显示边框</span>';
				htmlStr += '<a href="javascript:" class="newSubWindow unit-button">新建子窗口</a>';
				htmlStr += '<a href="javascript:" class="deleteFatherWindow unit-button">删除本窗体</a></div>';
			}
			htmlStr += '</div><div class="flash-topline"></div>';
		}
		
		htmlStr += '<div class="column float-right"></div></div>';
		
		// 添加到DOM中
		$('#window-container').append(htmlStr);
		
		if (this.config.readOnly && !fatherWindow.hasborder){
			$('#' + fatherWindow.id).removeClass('win-hasborder');
		}
		
		if (!(util.isEmptyObject(fatherWindow.width) || util.isEmptyObject(fatherWindow.height))){
			$('#' + fatherWindow.id).width(fatherWindow.width - this.config.adjustPiex);
			$('#' + fatherWindow.id).height(fatherWindow.height - this.config.adjustPiex);
		}
		
		if (!this.config.readOnly){
			// 添加可以自定义大小
			$('#' + fatherWindow.id).resizable({grid: this.config.subWinGrid});
			
			// 添加Sortable
			$('#' + fatherWindow.id + ' .column').sortable({
				connectWith: ".column",
				opacity: this.config.dragOpacity,
				revert: true
			}).disableSelection();
			
			var self = this;
			// 添加改变父窗体大小的事件
			$('#' + fatherWindow.id).bind("resizestop", function(){
				var fatherWin = self.boardData.getFatherWindow(fatherWindow.id);
				fatherWin.height = $(this).height() + self.config.adjustPiex;
				fatherWin.width = $(this).width() + self.config.adjustPiex;
			});
			
			// 绑定添加子窗体按钮事件
			$('#' + fatherWindow.id + ' .unit-title .newSubWindow').click(function(){
				var fatherId = $(this).parents('.win-con:first').attr("id");
				$("#newSubWinForm").dialog({
					width: 450,
					height: 330,
					modal: true,
					resizable: false,
					buttons: {
						"添加":function(){
							var title = document.newSubWinForm.title.value;
							var hasborder = document.newSubWinForm.hasborder.checked;
							var subDivNum = self.boardData.getFatherWindow(fatherId).seq++ + 1;
							self.createSubWindowWithUpdateData({'fatherId' : fatherId, 'id' : fatherId + '-' + subDivNum++, 'title' : title, 'hasborder' : hasborder});
							$(this).dialog('close');
						},
						"取消":function(){
							$(this).dialog('close');
						}
					}
				});
				
				
				
			});
			
			// 添加删除父窗体按钮的事件
			$('#' + fatherWindow.id + ' .unit-title .deleteFatherWindow').click(function(){
				if (confirm('确认删除本父窗口？')){
					var father = $(this).parents('.win-con:first');
					self.boardData.deleteFatherWindow(father.attr("id"));
					father.fadeOut(1000, function(){
						$(this).remove();
					});
				}
			});
			
			// 添加显示边框的事件
			$('#' + fatherWindow.id + ' .unit-title .hasBorderCheckbox').click(function(){
				var fatherId = $(this).parents('.win-con:first').attr("id");
				if (util.isEmptyObject($(this).attr('checked'))){
					self.boardData.getFatherWindow(fatherId).hasborder = false;
				} else {
					self.boardData.getFatherWindow(fatherId).hasborder = true;
				}
			});
			
		}

		// 绑定收起事件
		$('#' + fatherWindow.id + ' .win-con-headline .hideSubWindows').button().click(function(){
			$(this).parents('.win-con:first').children('.column').toggle();
		});
		
	},

	/**
	 *  @description 生成父窗口的代码，并更新JSONObject中的数据。在动态变更布局的时候被调用。其依赖了 createFatherWindow
	 *  @param {Object} fatherWindow 待生成父窗口对象
	 */
	createFatherWindowWithUpdateData : function(fatherWindow){
		var fatherDivNum = boardDesigner.boardData.seq++ + 1;
		var id = 'win-con-' + fatherDivNum;
		
		fatherWindow.id = id;
		fatherWindow.pos = this.boardData.getFatherWindowsLength() + 1;
		fatherWindow.seq = 0;
		
		// 更新HTML
		this.createFatherWindow(fatherWindow);
		// 更新JSONObject
		this.boardData.pushFatherWindow(fatherWindow);
	},

	/**
	 *  @description 生成子窗口的代码。
	 *  @param {Object} subWindow 待生成的子窗口对象
	 */
	createSubWindow : function(subWindow){
		// 生成需要生成的HTML代码
		var htmlStr = '<div id="' + subWindow.id +'" class="' + this.config.subDivStyle + 'unit-tip-thr flash-thr">';
		htmlStr += '<div class="unit-tip">';
		htmlStr += '<div class="unit-tip-con">';
    	htmlStr += '<span class="unit-tip-text">';
		htmlStr += '<img src="images/topics-tip.jpg" class="unit-tip-ico" />';
		htmlStr += subWindow.title + '</span><span class="unit-tip-num"></span></div></div>';
		htmlStr += '<div class="portlet-content"></div></div>';
		
		$('#' + subWindow.fatherId + ' .column').append(htmlStr);
		
		if (!this.config.readOnly){
			var str = '<a class="float-right ui-icon ui-icon-trash"></a>';
		} else {
			var str = '';
		}
		
		$('#' + subWindow.id).find(".unit-tip-con").append(str).end();

		// 获取需要改变大小的jQuery对象
		var content = $('#' + subWindow.id);
		
		// 设置宽度和高度
		if (!util.isEmptyObject(subWindow.width) && !util.isEmptyObject(subWindow.height)){
			content.width(subWindow.width - this.config.adjustPiex);
			content.height(subWindow.height - this.config.adjustPiex);
		}
		
		if (!this.config.readOnly){
			// grid为拖动的粒度 
			content.resizable({
				grid: this.config.subWinGrid,
				minHeight: this.config.subWinMinHeight,
				minWidth: this.config.subWinMinWidth,
				maxWidth: this.config.subWinMaxWidth,
				stop: function(){
					var subWin = self.boardData.getSubWindow(id);
					subWin.height = $(this).height() + self.config.adjustPiex;
					subWin.width = $(this).width() + self.config.adjustPiex;
				}
			});
			
			var self = this;
			// 给删除图标添加事件
			$('#' + subWindow.id + ' .ui-icon-trash').click(function() {
				if (confirm("是否删除本子窗体？")){
					$(this).parents('.sub-win:first').fadeOut(500, function(){
						self.boardData.deleteSubWindow($(this).attr('id'));
						$(this).remove();
					});
				}
			});
		}
		
	},

	/**
	 *  @description 生成子窗口的代码，并更新JSONObject的数据。
	 *  @param {Object} subWindow 待生成的子窗口对象
	 */
	createSubWindowWithUpdateData : function(subWindow){
		subWindow.pos = this.boardData.getSubWindowsLength(subWindow.fatherId) + 1;
		subWindow.width = this.config.subWinWidth;
		subWindow.height = this.config.subWinHeight;
		
		// 更新DOM
		this.createSubWindow(subWindow);
		// 更新JSONObject
		this.boardData.pushSubWindow(subWindow);
		
	},

	/**
	 *  @description 生成自定义窗口的代码。
	 *  @param {Object}} customWindow 待生成自定义窗口对象
	 */
	createCustomWindow : function(customWindow){
		var htmlStr = '<div id="' + customWindow.id + '" class="cus-win">';
		
		if (customWindow.type == 'remark'){
			if (util.isBlankString(customWindow.href)){
				htmlStr += customWindow.content
			} else {
				htmlStr += '<a href="' + customWindow.href + '" >' + customWindow.content + '</a>';
			}
		}
		if (!this.config.readOnly){
			htmlStr += '<a style="display:block; position:absolute; top:0px; right:5px; color:#0A6FFC;" class="removeCusWin" href="javascript:">x</a>';
		}
		
		htmlStr += '</div>'; 
		$('#' + this.config.mainContainer).append(htmlStr);
		
		var content = $('#' + customWindow.id);
		// 设置宽度和高度
		if (!(customWindow.width === null || customWindow.width === undefined || customWindow.height === null || customWindow.height === undefined)){
			content.width(customWindow.width  - this.config.adjustPiex);
			content.height(customWindow.height - this.config.adjustPiex);
		}
		
		// 设置位置
		content.css('top', customWindow.top).css('left', customWindow.left);
		
		if (!this.config.readOnly){
			var self = this;
			// 初始化自定义窗体使用自定义大小jQuery ui resizable组件
			$('#' + customWindow.id).resizable({
				grid: this.config.subWinGrid,
				stop: function(event, ui){
					var cusWin = self.boardData.getCustomWindow(customWindow.id);
					cusWin.height = $(this).height() + self.config.adjustPiex;
					cusWin.width = $(this).width() + self.config.adjustPiex;
				}
			});
			
			// 初始化自定义窗体使用拖动jQuery ui draggable组件
			$('#' + customWindow.id).draggable({
				opacity: this.config.dragOpacity,
				stop: function(event, ui){
					var cusWin = self.boardData.getCustomWindow(customWindow.id);
					cusWin.top = ui.position.top;
					cusWin.left = ui.position.left;
				}
			});
			
			// 添加删除自定义窗体事件
			$('#' + customWindow.id + ' .removeCusWin').click(function(){
				if (confirm("是否删除本自定义窗体？")){
					self.boardData.deleteCustomWindow(customWindow.id);
					$(this).parents('.cus-win:first').fadeOut(500);
				}
			});
			
		}
		
	},
	
	/**
	 *  @description 生成自定义窗口的代码，并更新JSONObject的数据。
	 *  @param {Object} customWindow 待生成自定义窗口对象
	 */
	createCustomWindowWithUpdateData : function(customWindow){
		var cusWinNum = boardDesigner.boardData.seq++ + 1;
		var id = 'cus-con-' + cusWinNum;
		
		var newCustomWin = {
			"type" : "remark",
			"id" : id,
			"content" : "",
			"width" : this.config.cusWinWidth,
			"height" : this.config.cusWinHeight,
			"top" : 0,
			"left" : -this.config.cusWinWidth/2 - 10
		};
		
		if (!util.isBlankString(customWindow.content)){
			newCustomWin.content = customWindow.content;
		}
		if (!util.isBlankString(customWindow.href)){
			newCustomWin.href = customWindow.href;
		}
		
		// 创建图形
		this.createCustomWindow(newCustomWin);
		// 更新JSONObject
		this.boardData.pushCustomWindow(newCustomWin);
		
	},
	
	/**
	 *  @description 保存信息到Cookie
	 */
	save : function(){
		var str = JSON.stringify(this.boardData);
		$.cookie('boardData', str, {expires: 7});
	},

	/**
	 *  @description 清除Cookie中的数据
	 */
	clear : function(){
		$.cookie('boardData', null);
	}

}
